﻿/* **************************************************************************
 *
 * Copyright 2007-2010 Jeff Hardy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * *************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Client.Win32;
using Microsoft.Web.Management.Server;
using NWSGI.Management;

namespace NWSGI.ManagementClient
{
    internal abstract class WsgiPropertyGridObject : PropertyGridObject
    {
        public WsgiPropertyGridObject(ModulePropertiesPage page) : base(page) { }

        protected override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            PropertyDescriptorCollection properties = base.GetProperties(attributes);
            List<PropertyDescriptor> newProperties = new List<PropertyDescriptor>();
            Type thisType = GetType();

            foreach(PropertyDescriptor descriptor in properties)
            {
                WsgiDisplayNameAttribute dna = (WsgiDisplayNameAttribute)(descriptor.Attributes[typeof(WsgiDisplayNameAttribute)]);

                if(dna != null)
                {
                    DisplayNameAttribute newAttrib = GetDisplayNameAttribute(dna.FriendlyName, dna.ConfigPropertyName);
                    newProperties.Add(TypeDescriptor.CreateProperty(thisType, descriptor, newAttrib));
                }
                else
                {
                    newProperties.Add(descriptor);
                }
            }

            return new PropertyDescriptorCollection(newProperties.ToArray());
        }
    }

    public enum FrameOptions
    {
        Off, On, Full
    }

    public enum CompilationOptions
    {
        Adaptive, Compiled
    }

    internal class WsgiInfo : WsgiPropertyGridObject
    {
        private PropertyBag bag;
        private NwsgiPage page;

        public WsgiInfo(NwsgiPage page, PropertyBag properties) : base(page)
        {
            this.page = page;
            Initialize(properties);
        }

        internal void Initialize(PropertyBag properties)
        {
            this.bag = properties;

            this.wildcard = new WildcardProperties(page, bag);
        }

        [WsgiDisplayNameAttribute("Enable Extensions", "enableExtensions")]
        [Description("Enable NWSGI's extensions ot the WSGI protocol.")]
        [DefaultValue(false)]
        public bool EnableExtensions
        {
            get { return bag[(int)PropertyKeys.EnableExtensionsKey] as bool? ?? false; }
            set { bag[(int)PropertyKeys.EnableExtensionsKey] = value; }
        }

        [WsgiDisplayNameAttribute("Compilation", "compilation")]
        [Description("Control how IronPython compiles code.")]
        [DefaultValue(CompilationOptions.Adaptive)]
        public CompilationOptions Compilation
        {
            get { return (CompilationOptions)(bag[(int)PropertyKeys.CompilationKey] as int? ?? (int)CompilationOptions.Adaptive); }
            set { bag[(int)PropertyKeys.CompilationKey] = (int)value; }
        }

        [WsgiDisplayNameAttribute("Frames", "frames")]
        [Description("Enable sys._getframe.")]
        [DefaultValue(FrameOptions.Off)]
        public FrameOptions Frames
        {
            get { return (FrameOptions)(bag[(int)PropertyKeys.FramesKey] as int? ?? (int)FrameOptions.Off); }
            set { bag[(int)PropertyKeys.FramesKey] = (int)value; }
        }

        [WsgiDisplayNameAttribute("Tracing", "tracing")]
        [Description("Enable sys.settrace.")]
        [DefaultValue(false)]
        public bool Tracing
        {
            get { return (bool)(bag[(int)PropertyKeys.TracingKey] as bool? ?? false); }
            set { bag[(int)PropertyKeys.TracingKey] = value; }
        }

        [WsgiDisplayNameAttribute("Lightweight Scopes", "lightweightScopes")]
        [Description("Use lightweight scopes.")]
        [DefaultValue(false)]
        public bool LightweightScopes
        {
            get { return (bool)(bag[(int)PropertyKeys.LightweightScopesKey] as bool? ?? false); }
            set { bag[(int)PropertyKeys.LightweightScopesKey] = value; }
        }

        [WsgiDisplayNameAttribute("Enable Profiler", "enableProfiler")]
        [Description("Enable the profiler.")]
        [DefaultValue(false)]
        public bool EnableProfiler
        {
            get { return (bool)(bag[(int)PropertyKeys.EnableProfilerKey] as bool? ?? false); }
            set { bag[(int)PropertyKeys.EnableProfilerKey] = value; }
        }

        private WildcardProperties wildcard;
        [WsgiDisplayNameAttribute("Wildcard")]
        [Description("When using a wildcard mapping, either the path to the module or ':callable' to use a module descriptor.")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public WildcardProperties Wildcard
        {
            get { return this.wildcard; }
        }

        public class WildcardProperties : WsgiPropertyGridObject
        {
            private PropertyBag bag;

            public WildcardProperties(NwsgiPage page, PropertyBag bag)
                : base(page)
            {
                this.bag = bag;
            }

            [WsgiDisplayNameAttribute("Physical Path", "physicalPath")]
            [Description("Physical path of the wildcard handler.")]
            public string PhysicalPath
            {
                get { return bag[(int)PropertyKeys.WildcardPhysicalPathKey] as string; }
                set { bag[(int)PropertyKeys.WildcardPhysicalPathKey] = value; }
            }

            [WsgiDisplayNameAttribute("Callable", "callable")]
            [Description("Name of the callable object.")]
            public string Callable
            {
                get { return bag[(int)PropertyKeys.WildcardCallableKey] as string; }
                set { bag[(int)PropertyKeys.WildcardCallableKey] = value; }
            }

            public string[] ToArray()
            {
                return new string[] { PhysicalPath, Callable };
            }

            public override string ToString()
            {
                return string.Empty;
            }
        }
    }

    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    sealed class WsgiDisplayNameAttribute : Attribute
    {
        public WsgiDisplayNameAttribute(string friendlyName) : this(friendlyName, string.Empty) { }

        public WsgiDisplayNameAttribute(string friendlyName, string configName)
        {
            this.FriendlyName = friendlyName;
            this.ConfigPropertyName = configName;
        }

        public string FriendlyName { get; private set; }
        public string ConfigPropertyName { get; private set; }
    }
}
